home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Extra 1996 #3 / AmigaPlus_CD-ROM-EXTRA_Nr.3.bin / aminet-spiele / role on / larn / main.c < prev    next >
C/C++ Source or Header  |  1997-12-31  |  41KB  |  1,331 lines

  1. /* main.c */
  2.  
  3. #ifdef MSDOS
  4. #include "errno.h"
  5. #include "setjmp.h"
  6. #include "stdlib.h"
  7. #endif
  8.  
  9. #include "header.h"
  10. #include "larndefs.h"
  11. #include "monsters.h"
  12. #include "objects.h"
  13. #include "player.h"
  14. #include "patchlev.h"
  15.  
  16. #ifndef AMIGA
  17. # ifndef MSDOS
  18. #  ifndef VMS
  19. #   include <pwd.h>
  20. #  endif VMS
  21. # endif MSDOS
  22. #endif AMIGA
  23.  
  24. extern char move_no_pickup;
  25. int dropflag=0; /* if 1 then don't lookforobject() next round */
  26. int rmst=80;    /*  random monster creation counter     */
  27. int userid;     /* the players login user id number */
  28. char nowelcome=0,nomove=0; /* if (nomove) then don't count next iteration as a
  29.                               move */
  30. static char viewflag=0;    /* if viewflag then we have done a 99 stay here
  31.                               and don't showcell in the main loop */
  32. char restorflag=0;         /* 1 means restore has been done    */
  33. char prompt_mode = 0;         /* 1 if prompting for actions */
  34.  
  35. #ifdef MSDOS
  36.  
  37. static char cmdhelp[] = "\
  38. Cmd line format: larn [-slicnhp] [-o<optsfile>] [-##] [++]\n\
  39.   -s   show the scoreboard\n\
  40.   -l   show the logfile (wizard id only)\n\
  41.   -i   show scoreboard with inventories of dead characters\n\
  42.   -c   create new scoreboard (wizard id only)\n\
  43.   -n   suppress welcome message on starting game\n\
  44.   -##  specify level of difficulty (example: -5)\n\
  45.   -h   print this help text\n\
  46.   -p   prompt for actions on objects\n\
  47.   ++   restore game from checkpoint file\n\
  48.   -o<optsfile>   specify larnopts filename to be used instead of \"larn.opt\"\n\
  49. ";
  50.  
  51. # else
  52.  
  53. static char cmdhelp[] = "\
  54. Cmd line format: larn [-slicnhp] [-o<optsfile>] [-##] [++]\n\
  55.   -s   show the scoreboard\n\
  56.   -l   show the logfile (wizard id only)\n\
  57.   -i   show scoreboard with inventories of dead characters\n\
  58.   -c   create new scoreboard (wizard id only)\n\
  59.   -n   suppress welcome message on starting game\n\
  60.   -##  specify level of difficulty (example: -5)\n\
  61.   -h   print this help text\n\
  62.   -p   prompt for actions on objects\n\
  63.   ++   restore game from checkpoint file\n\
  64.   -o<optsfile>   specify .larnopts filename to be used instead of \"~/.larnopts\"\n\
  65. ";
  66.  
  67. # endif
  68.  
  69. #ifdef MSDOS
  70. int save_mode = 0;      /* 1 if doing a save game */
  71. jmp_buf save_jbuf;      /* To recover from disk full errors */
  72. #endif
  73.  
  74. #ifdef VT100
  75. static char *termtypes[] = { "vt100", "vt101", "vt102", "vt103", "vt125",
  76.     "vt131", "vt140", "vt180", "vt220", "vt240", "vt241", "vt320", "vt340",
  77.     "vt341"  };
  78. #endif
  79.  
  80. #ifdef VMS
  81. # define EXIT_FAILURE
  82. # define EXIT_SUCCESS 1
  83. #else
  84. # define EXIT_FAILURE 1
  85. # define EXIT_SUCCESS 0
  86. #endif
  87.  
  88. /*
  89.     ************
  90.     MAIN PROGRAM
  91.     ************
  92. */
  93. main(argc,argv)
  94.     int argc;
  95.     char **argv;
  96.     {
  97.     register int i,j;
  98.     int hard = -1;
  99.     char *ptr=0;
  100. #ifdef VT100
  101.     char *ttype;
  102. #endif
  103. #ifndef MSDOS
  104.     struct passwd *pwe,*getpwuid();
  105. #endif
  106.  
  107. /*
  108.  *  first task is to identify the player
  109.  */
  110. #ifndef VT100
  111.     init_term();    /* setup the terminal (find out what type) for termcap */
  112. #endif
  113. #ifdef AMIGA
  114.     AmInit(); /* Open console device */
  115.     ptr = "AMIGAN";
  116. #else
  117. #ifdef MSDOS
  118.     ptr = "PLAYER";
  119. #else
  120. #ifdef VMS
  121.     ptr = getenv("USER");
  122. #else
  123.     if (((ptr = getlogin()) == 0) || (*ptr==0)) /* try to get login name */
  124.       if (pwe=getpwuid(getuid())) /* can we get it from /etc/passwd? */
  125.         ptr = pwe->pw_name;
  126.       else
  127.       if ((ptr = getenv("USER")) == 0)
  128.         if ((ptr = getenv("LOGNAME")) == 0)
  129.           {
  130.           noone: write(2, "Can't find your logname.  Who Are You?\n",39);
  131.                  exit();
  132.           }
  133.     if (ptr==0) goto noone;
  134.     if (strlen(ptr)==0) goto noone;
  135. #endif /* VMS */
  136. #endif /* MSDOS */
  137. #endif /* AMIGA */
  138.  
  139. /*
  140.  *  second task is to prepare the pathnames the player will need
  141.  */
  142.     strcpy(loginname,ptr); /* save loginname of the user for logging purposes */
  143.     strcpy(logname,ptr);    /* this will be overwritten with the players name */
  144.  
  145. /* Set up the input and output buffers.
  146.  */
  147.     lpbuf    = (char *)malloc((5* BUFBIG)>>2);  /* output buffer */
  148.     inbuffer = (char *)malloc((5*MAXIBUF)>>2);  /* output buffer */
  149.     if ((lpbuf==0) || (inbuffer==0)) 
  150.         died(-285); /* malloc() failure */
  151.  
  152. # ifdef MSDOS
  153.     /* LARNHOME now comes from the options file, so it must be read in
  154.      * before constructing the other file names.  Unfortunately we have
  155.      * to look for the -o option now.
  156.      */
  157.     strcpy(optsfile, LARNOPTS);
  158.     for (i = 1; i < argc; i++)
  159.         if (strncmp(argv[i], "-o", 2) == 0) 
  160.             {
  161.             argv[i][0] = 0;         /* remove this argv */
  162.             if (argv[i][2] != '\0')
  163.                 strncpy(optsfile, &argv[i][2], PATHLEN);
  164.             else
  165.                 {
  166.                 strncpy(optsfile, argv[i + 1], PATHLEN);
  167.                 argv[i + 1][0] = 0; /* and this argv */
  168.                 }
  169.             optsfile[PATHLEN - 1] = 0;
  170.             break;
  171.             }
  172.     readopts();
  173.     append_slash(larndir);
  174.  
  175.     /* Savefile and swapfile can be given explicitly as options
  176.      */
  177.     if (!savefilename[0]) 
  178.         {
  179.         strcpy(savefilename, larndir);
  180.         strcat(savefilename, SAVEFILE);
  181.         }
  182.     if (!swapfile[0]) 
  183.         {
  184.         strcpy(swapfile, larndir);
  185.         strcat(swapfile, SWAPFILE);
  186.         }
  187.     strcpy(scorefile, larndir);
  188.     strcpy(logfile, larndir);
  189.     strcpy(helpfile, larndir);
  190.     strcpy(larnlevels, larndir);
  191.     strcpy(fortfile, larndir);
  192.     strcpy(playerids, larndir);
  193.     strcpy(ckpfile, larndir);
  194.  
  195. # else /* MSDOS */
  196.  
  197.     if ((ptr = getenv("HOME")) == 0) 
  198.         ptr = ".";
  199. #ifdef SAVEINHOME
  200.     /* save file name in home directory */
  201. # ifdef VMS
  202.     sprintf(savefilename, "%s%s",ptr, SAVEFILE);
  203. # else
  204.     sprintf(savefilename, "%s/%s",ptr, SAVEFILE);
  205. # endif VMS
  206. #else
  207.     strcat(savefilename,logname);   /* prepare savefile name */
  208.     strcat(savefilename,".sav");    /* prepare savefile name */
  209. #endif
  210. #ifdef VMS
  211.     sprintf(optsfile, "%s%s",ptr, LARNOPTS);   /* the options filename */
  212. #else
  213. #ifdef AMIGA
  214.     sprintf(optsfile, "%s%s", LARNHOME, LARNOPTS);   /* the options filename */
  215. #else
  216.     sprintf(optsfile, "%s/%s",ptr, LARNOPTS);   /* the options filename */
  217. #endif AMIGA
  218. #endif VMS
  219.  
  220. # endif /* MSDOS */
  221.  
  222.     strcat(scorefile, SCORENAME);   /* the larn scoreboard filename */
  223.     strcat(logfile, LOGFNAME);      /* larn activity logging filename */
  224.     strcat(helpfile, HELPNAME);     /* the larn on-line help file */
  225.     strcat(larnlevels, LEVELSNAME); /* the pre-made cave level data file */
  226.     strcat(fortfile, FORTSNAME);    /* the fortune data file name */
  227.     strcat(playerids, PLAYERIDS);   /* the playerid data file name */
  228.     strcat(ckpfile, CKPFILE);
  229.  
  230. # ifdef TIMECHECK
  231.     strcat(holifile, HOLIFILE);     /* the holiday data file name */
  232. # endif
  233.  
  234. #ifdef VT100
  235. /*
  236.  *  check terminal type to avoid users who have not vt100 type terminals
  237.  */
  238.     ttype = getenv("TERM");
  239.     for (j=1, i=0; i<sizeof(termtypes)/sizeof(char *); i++)
  240.         if (strcmp(ttype,termtypes[i]) == 0) { j=0;  break; }
  241.     if (j)
  242.         {
  243.         lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush();
  244.         exit(EXIT_FAILURE);
  245.         }
  246. #endif
  247.  
  248. /*
  249.  *  now make scoreboard if it is not there (don't clear) 
  250.  */
  251.     if (access(scorefile,0) == -1) /* not there */
  252.         makeboard();
  253.  
  254. /*
  255.  *  now process the command line arguments 
  256.  */
  257.     for (i=1; i<argc; i++)
  258.         {
  259.         if (argv[i][0] == '-')
  260.           switch(argv[i][1])
  261.             {
  262.             case 's':          /* show scoreboard   */
  263.                 showscores();
  264.                 exit(EXIT_SUCCESS);
  265.  
  266.             case 'l':          /* show log file     */
  267.                 diedlog();
  268.                 exit(EXIT_SUCCESS);
  269.  
  270.             case 'i':          /* show all scoreboard */
  271.                 showallscores();
  272.                 exit(EXIT_SUCCESS);
  273.  
  274.             case 'c':          /* anyone with password can create scoreboard */
  275.                 lprcat("Preparing to initialize the scoreboard.\n");
  276.                 if (getpassword() != 0)  /*make new scoreboard*/
  277.                     {
  278.                     makeboard();
  279.                     lprc('\n');
  280.                     showscores();
  281.                     }
  282.                 exit(EXIT_SUCCESS);
  283.  
  284.             case 'n':          /* no welcome msg   */
  285.                 nowelcome=1;
  286.                 argv[i][0]=0;
  287.                 break;
  288.  
  289.             case '0': case '1': case '2': case '3': case '4': case '5':
  290.             case '6': case '7': case '8': case '9': /* for hardness */
  291.                 hard = atoi(&argv[i][1]);
  292.                 break;
  293.  
  294.             case 'h':          /* print out command line arguments */
  295.             case '?':
  296.                 write(1,cmdhelp,sizeof(cmdhelp));
  297.                 exit(EXIT_SUCCESS);
  298.  
  299.             case 'o':          /* specify a .larnopts filename */
  300.                 if (argv[i]+2 != '\0')
  301.                     strncpy(optsfile,argv[i]+2,127);
  302.                 else
  303.                     {
  304.                     strncpy( optsfile, argv[i+1][0], 127 );
  305.                     argv[i+1][0] = '\0';
  306.                     }
  307.                 break;
  308.  
  309.             case 'p':          /* set 'prompt_mode' flag */
  310.                 prompt_mode = 1 ;
  311.                 break ;
  312.  
  313.             default:
  314.                 printf("Unknown option <%s>\n",argv[i]);
  315.                 write(1,cmdhelp,sizeof(cmdhelp));
  316.                 exit(EXIT_SUCCESS);
  317.             };
  318.  
  319.         if (strcmp(argv[i], "++") == 0)
  320.             restorflag = 1;
  321.     }
  322.  
  323. #ifndef MSDOS
  324.     readopts();     /* read the options file if there is one */
  325. #endif
  326.  
  327. #ifdef TIMECHECK
  328. /*
  329.  *  this section of code checks to see if larn is allowed during working hours
  330.  */
  331.     if (dayplay==0) /* check for not-during-daytime-hours */
  332.       if (playable())
  333.         {
  334.         write(2,"Sorry, Larn can not be played during working hours.\n",52);
  335.         exit(EXIT_SUCCESS);
  336.         }
  337. #endif TIMECHECK
  338.  
  339. #ifdef UIDSCORE
  340.     userid = geteuid(); /* obtain the user's effective id number */
  341. #else UIDSCORE
  342.     userid = getplid(logname);  /* obtain the players id number */
  343. #endif UIDSCORE
  344. #ifdef VMS
  345.     wisid = userid;
  346. #endif
  347.     if (userid < 0) 
  348.         { 
  349.         write(2,"Can't obtain playerid\n",22);
  350.         exit(EXIT_SUCCESS);
  351.         }
  352.  
  353. #ifdef HIDEBYLINK
  354. /*
  355.  *  this section of code causes the program to look like something else to ps
  356.  */
  357.     if (strcmp(psname,argv[0])) /* if a different process name only */
  358.         {
  359.         if ((i=access(psname,1)) < 0)
  360.             {       /* link not there */
  361.             if (link(argv[0],psname)>=0)
  362.                 {
  363.                 argv[0] = psname;   execv(psname,argv);
  364.                 }
  365.             }
  366.         else
  367.             unlink(psname);
  368.         }
  369.  
  370.     for (i=1; i<argc; i++)
  371.         {
  372.         szero(argv[i]); /* zero the argument to avoid ps snooping */
  373.         }
  374. #endif HIDEBYLINK
  375.  
  376. /*
  377.  *  He really wants to play, so malloc the memory for the dungeon.
  378.  */
  379. # ifdef MSDOS
  380.     allocate_memory();
  381. # else
  382.     cell = (struct cel *)malloc(sizeof(struct cel)*(MAXLEVEL+MAXVLEVEL)*MAXX*MAXY);
  383.     if (cell == 0) died(-285);  /* malloc failure */
  384. # endif
  385.     lcreat((char*)0);   
  386.     newgame();      /*  set the initial clock  */
  387.  
  388.     if (restorflag == 1)           /* restore checkpoint file */
  389.         {
  390.         clear();
  391.         hitflag = 1;
  392.         restoregame(ckpfile);
  393.         }
  394.     else if (access(savefilename,0)==0)   /* restore game if need to */
  395.         {
  396.         clear();    
  397.         restorflag = 1;
  398.         hitflag=1;  
  399.         restoregame(savefilename);  /* restore last game    */
  400.         }
  401.     sigsetup();     /* trap all needed signals  */
  402.     setupvt100();   /*  setup the terminal special mode             */
  403.     sethard(hard);  /* set up the desired difficulty                */
  404.     if (c[HP]==0)   /* create new game */
  405.         {
  406.         makeplayer();   /*  make the character that will play           */
  407.         newcavelevel(0);/*  make the dungeon                            */
  408.         predostuff = 1; /* tell signals that we are in the welcome screen */
  409.         if (nowelcome==0)
  410.             welcome();     /* welcome the player to the game */
  411. # ifdef MSDOS
  412.         /* Display their mail if they've just won the previous game
  413.          */
  414.         checkmail();
  415. # endif
  416.         }
  417.  
  418.     lprc(T_INIT);   /* Reinit the screen because of welcome and check mail
  419.                      * having embedded escape sequences.*/
  420.     drawscreen();   /*  show the initial dungeon                    */
  421.     predostuff = 2; /* tell the trap functions that they must do a showplayer()
  422.                from here on */
  423.     /* nice(1); /* games should be run niced */
  424.     yrepcount = hit2flag = 0;
  425.     /* init previous player position to be current position, so we don't
  426.        reveal any stuff on the screen prematurely.
  427.     */
  428.     oldx = playerx ;
  429.     oldy = playery;
  430.     gtime = -1;
  431.  
  432.     /* MAINLOOP
  433.        find objects, move stuff, get commands, regenerate
  434.     */
  435.     while (1)
  436.         {
  437.         if (dropflag==0)
  438.             /* see if there is an object here.
  439.  
  440.                If in prompt mode, identify and prompt; else
  441.                identify, pickup if ( auto pickup and not move-no-pickup ),
  442.                never prompt.
  443.             */
  444.             if (prompt_mode)
  445.                 lookforobject( TRUE, FALSE, TRUE );
  446.             else
  447.                 lookforobject( TRUE, ( auto_pickup && !move_no_pickup ), FALSE );
  448.             else
  449.                 dropflag=0; /* don't show it just dropped an item */
  450.  
  451.         /* handle global activity
  452.            update game time, move spheres, move walls, move monsters
  453.            all the stuff affected by TIMESTOP and HASTESELF
  454.         */
  455.         if (c[TIMESTOP] <= 0)
  456.             if (c[HASTESELF] == 0 ||
  457.                (c[HASTESELF] & 1) == 0)
  458.                 {
  459.                 gtime++;
  460.                 movsphere();
  461.  
  462.                 if (hitflag==0)
  463.                     {
  464.                     if (c[HASTEMONST])
  465.                         movemonst();
  466.                     movemonst();
  467.                     }
  468.                 }
  469.  
  470.         /* show stuff around the player
  471.         */
  472.         if (viewflag==0)
  473.             showcell(playerx,playery);
  474.         else
  475.             viewflag=0;
  476.  
  477.         if (hit3flag)
  478.             lflushall();
  479.         hitflag=hit3flag=0;
  480.         bot_linex();    /* update bottom line */
  481.  
  482.         /* get commands and make moves
  483.         */
  484.         nomove=1;
  485.         while (nomove)
  486.             {
  487.             if (hit3flag)
  488.                 lflushall();
  489.             nomove=0;
  490.             parse();
  491.             }
  492.         regen();            /*  regenerate hp and spells            */
  493.         if (c[TIMESTOP]==0)
  494.             if (--rmst <= 0)
  495.                 {
  496.                 rmst = 120-(level<<2);
  497.                 fillmonst(makemonst(level));
  498.                 }
  499.         }
  500.     }
  501.  
  502. /*
  503.     subroutine to randomly create monsters if needed
  504.  */
  505. static randmonst()
  506.     {
  507.     if (c[TIMESTOP]) return;    /*  don't make monsters if time is stopped  */
  508.     if (--rmst <= 0)
  509.         {
  510.         rmst = 120 - (level<<2);  fillmonst(makemonst(level));
  511.         }
  512.     }
  513.  
  514.  
  515. /*
  516.     parse()
  517.  
  518.     get and execute a command
  519.  */
  520. static parse()
  521.     {
  522.     register int i,j,k,flag;
  523.     extern showeat(),showquaff(),showread();
  524.  
  525.     while   (1)
  526.         {
  527.         k = yylex();
  528.         switch(k)   /*  get the token from the input and switch on it   */
  529.             {
  530.             case 'h':   moveplayer(4);  return;     /*  west        */
  531.             case 'H':   run(4);         return;     /*  west        */
  532.             case 'l':   moveplayer(2);  return;     /*  east        */
  533.             case 'L':   run(2);         return;     /*  east        */
  534.             case 'j':   moveplayer(1);  return;     /*  south       */
  535.             case 'J':   run(1);         return;     /*  south       */
  536.             case 'k':   moveplayer(3);  return;     /*  north       */
  537.             case 'K':   run(3);         return;     /*  north       */
  538.             case 'u':   moveplayer(5);  return;     /*  northeast   */
  539.             case 'U':   run(5);         return;     /*  northeast   */
  540.             case 'y':   moveplayer(6);  return;     /*  northwest   */
  541.             case 'Y':   run(6);         return;     /*  northwest   */
  542.             case 'n':   moveplayer(7);  return;     /*  southeast   */
  543.             case 'N':   run(7);         return;     /*  southeast   */
  544.             case 'b':   moveplayer(8);  return;     /*  southwest   */
  545.             case 'B':   run(8);         return;     /*  southwest   */
  546.  
  547.             case '.':                               /*  stay here       */
  548.                 if (yrepcount) 
  549.                     viewflag=1;
  550.                 return;
  551.  
  552.             case 'c':
  553.                 yrepcount=0;
  554.                 cast();
  555.                 return;     /*  cast a spell    */
  556.  
  557.             case 'd':
  558.                 yrepcount=0;
  559.                 if (c[TIMESTOP]==0)
  560.                     dropobj();
  561.                 return; /*  to drop an object   */
  562.  
  563.             case 'e':
  564.                 yrepcount=0;
  565.                 if (c[TIMESTOP]==0)
  566.                     if (!floor_consume( OCOOKIE, "eat" ))
  567.                         consume( OCOOKIE, "eat", showeat );
  568.                 return; /*  to eat a fortune cookie */
  569.  
  570.             case 'g':   
  571.                 yrepcount = 0 ;
  572.                 cursors();
  573.                 lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long)packweight());
  574.                 break ;
  575.  
  576.             case 'i':       /* inventory */
  577.                 yrepcount=0;
  578.                 nomove=1;
  579.                 showstr(FALSE);
  580.                 return;
  581.  
  582.             case 'p':           /* pray at an altar */
  583.                 yrepcount = 0;
  584.                 if (!prompt_mode)
  585.                     pray_at_altar();
  586.                 else
  587.                     nomove = 1;
  588.                 return;
  589.  
  590.             case 'q':           /* quaff a potion */
  591.                 yrepcount=0;
  592.                 if (c[TIMESTOP]==0)
  593.                     if (!floor_consume( OPOTION, "quaff"))
  594.                         consume( OPOTION, "quaff", showquaff );
  595.                 return;
  596.  
  597.             case 'r':
  598.                 yrepcount=0;
  599.                 if (c[BLINDCOUNT])
  600.                     {
  601.                     cursors();
  602.                     lprcat("\nYou can't read anything when you're blind!");
  603.                     }
  604.                 else if (c[TIMESTOP]==0)
  605.                     if (!floor_consume( OSCROLL, "read" ))
  606.                         if (!floor_consume( OBOOK, "read" ))
  607.                             consume( OSCROLL, "read", showread );
  608.                 return;     /*  to read a scroll    */
  609.  
  610.             case 's':
  611.                 yrepcount = 0 ;
  612.                 if (!prompt_mode)
  613.                     sit_on_throne();
  614.                 else
  615.                     nomove = 1;
  616.                 return ;
  617.  
  618.             case 't':                       /* Tidy up at fountain */
  619.                 yrepcount = 0 ;
  620.                 if (!prompt_mode)
  621.                     wash_fountain() ;
  622.                 else
  623.                     nomove = 1;
  624.                 return ;
  625.  
  626.             case 'v':
  627.                 yrepcount=0;
  628.                 nomove = 1;
  629.                 cursors();
  630.                 lprintf("\nCaverns of Larn, Version %d.%d.%d, Diff=%d",(long)VERSION,(long)SUBVERSION,(long)PATCHLEVEL,(long)c[HARDGAME]);
  631.                 if (wizard)
  632.                     lprcat(" Wizard");
  633.                 if (cheat) 
  634.                     lprcat(" Cheater");
  635.                 lprcat("\nThis version of Larn by Kevin Routley");
  636.                 return;
  637.  
  638.             case 'w':                       /*  wield a weapon */
  639.                 yrepcount=0;
  640.                 wield();
  641.                 return;
  642.  
  643.             case 'A':
  644.                 yrepcount = 0;
  645.                 if (!prompt_mode)
  646.                     desecrate_altar();
  647.                 else
  648.                     nomove = 1;
  649.                 return;
  650.  
  651.             case 'C':                       /* Close something */
  652.                 yrepcount = 0 ;
  653.                 if (!prompt_mode)
  654.                     close_something();
  655.                 else
  656.                     nomove = 1;
  657.                 return;
  658.  
  659.             case 'D':                       /* Drink at fountain */
  660.                 yrepcount = 0 ;
  661.                 if (!prompt_mode)
  662.                     drink_fountain() ;
  663.                 else
  664.                     nomove = 1;
  665.                 return ;
  666.  
  667.             case 'E':               /* Enter a building */
  668.                 yrepcount = 0 ;
  669.                 if (!prompt_mode)
  670.                     enter() ;
  671.                 else
  672.                     nomove = 1;
  673.                 break ;
  674.  
  675.             case 'I':              /*  list spells and scrolls */
  676.                 yrepcount=0;
  677.                 seemagic(0);
  678.                 nomove=1;
  679.                 return;
  680.  
  681.             case 'O':               /* Open something */
  682.                 yrepcount = 0 ;
  683.                 if (!prompt_mode)
  684.                     open_something();
  685.                 else
  686.                     nomove = 1;
  687.                 return;
  688.  
  689.             case 'P':
  690.                 cursors();
  691.                 yrepcount = 0;
  692.                 nomove = 1;
  693.                 if (outstanding_taxes>0)
  694.                     lprintf("\nYou presently owe %d gp in taxes.",(long)outstanding_taxes);
  695.                 else
  696.                     lprcat("\nYou do not owe any taxes.");
  697.                 return;
  698.  
  699.             case 'Q':    /*  quit        */
  700.                 yrepcount=0;
  701.                 quit();
  702.                 nomove=1;
  703.                 return;
  704.  
  705.             case 'R' :          /* remove gems from a throne */
  706.                 yrepcount = 0 ;
  707.                 if (!prompt_mode)
  708.                     remove_gems( );
  709.                 else
  710.                     nomove = 1;
  711.                 return ;
  712.  
  713. # ifdef MSDOS
  714.             case 'S':
  715.                 /* Set up error recovery
  716.                  */
  717.                 if (setjmp(save_jbuf) != 0) {
  718.  
  719.                     /* can't use lwclose!
  720.                      */
  721.                     if (lfd > 2)
  722.                         close(lfd);
  723.                     lcreat(NULL);
  724.                     setscroll();
  725.                     cursors();
  726.                     lprcat("\nSave failed !\n");
  727.                     if (errno == ENOSPC)
  728.                         lprcat("Disk is full !\n");
  729.                     beep();
  730.                     (void) unlink(savefilename);
  731.                     save_mode = 0;
  732.                     yrepcount = 0;
  733.                     nomove = 1;
  734.                     break;
  735.                 }
  736.  
  737.                 /* And do the save.
  738.                  */
  739.                 cursors();
  740.                 lprintf("\nSaving to `%s' . . . ", savefilename);
  741.                 lflush();
  742.                 save_mode = 1;
  743.                 savegame(savefilename);
  744.                 clear();
  745.                 lflush();
  746.                 wizard=1;
  747.                 died(-257); /* doesn't return */
  748.                 break;
  749. # else
  750.             case 'S':   clear();  lprcat("Saving . . ."); lflush();  
  751.                         savegame(savefilename); wizard=1; died(-257);   /*  save the game - doesn't return  */
  752. # endif MSDOS
  753.  
  754.             case 'T':   yrepcount=0;    cursors();  if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else
  755.                                         if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); }
  756.                         else lprcat("\nYou aren't wearing anything");
  757.                         return;
  758.  
  759.             case 'W':
  760.                 yrepcount=0;
  761.                 wear();
  762.                 return; /*  wear armor  */
  763.  
  764.             case 'Z':
  765.                 yrepcount=0;
  766.                 if (c[LEVEL]>9) 
  767.                     { 
  768.                     oteleport(1);
  769.                     return; 
  770.                     }
  771.                 cursors(); 
  772.                 lprcat("\nAs yet, you don't have enough experience to use teleportation");
  773.                 return; /*  teleport yourself   */
  774.  
  775.             case ' ':   yrepcount=0;    nomove=1;  return;
  776.  
  777. # ifdef MSDOS
  778.             case 'D'-64:
  779.                 yrepcount = 0;
  780.                 nomove = 1;
  781.                 levelinfo();
  782.                 return;
  783. # endif
  784.  
  785.             case 'L'-64:  yrepcount=0;  drawscreen();  nomove=1; return;    /*  look        */
  786.  
  787. #if WIZID
  788. #ifdef EXTRA
  789.             case 'A'-64:    yrepcount=0;    nomove=1; if (wizard) { diag(); return; }  /*   create diagnostic file */
  790.                         return;
  791. #endif
  792. #endif
  793.             case '<':                       /* Go up stairs or vol shaft */
  794.                 yrepcount = 0 ;
  795.                 if (!prompt_mode)
  796.                     up_stairs();
  797.         else
  798.             nomove = 1;
  799.                 return ;
  800.  
  801.             case '>':                       /* Go down stairs or vol shaft*/
  802.                 yrepcount = 0 ;
  803.                 if (!prompt_mode)
  804.                     down_stairs();
  805.         else
  806.             nomove = 1;
  807.                 return ;
  808.  
  809.             case '?':                       /* give the help screen */
  810.                 yrepcount=0;
  811.                 help();
  812.                 nomove=1;
  813.                 return; 
  814.  
  815.         case ',':                       /* pick up an item */
  816.             yrepcount = 0 ;
  817.             if (!prompt_mode)
  818.             /* pickup, don't identify or prompt for action */
  819.             lookforobject( FALSE, TRUE, FALSE );
  820.         else
  821.             nomove = 1;
  822.         return;
  823.  
  824.             case ':':                       /* look at object */
  825.                 yrepcount = 0 ;
  826.                 if (!prompt_mode)
  827.             /* identify, don't pick up or prompt for action */
  828.                     lookforobject( TRUE, FALSE, FALSE );
  829.                 nomove = 1;  /* assumes look takes no time */
  830.                 return;
  831.  
  832.         case '@':       /* toggle auto-pickup */
  833.             yrepcount = 0 ;
  834.             nomove = 1;
  835.             cursors();
  836.             lprcat("\nAuto pickup: ");
  837.             auto_pickup = !auto_pickup;
  838.             if (auto_pickup)
  839.                 lprcat("On.");
  840.             else
  841.                 lprcat("Off.");
  842.             return;
  843.  
  844.         case '/':        /* identify object/monster */
  845.             specify_object();
  846.             nomove = 1 ;
  847.             yrepcount = 0 ;
  848.             return;
  849.  
  850.         case '^':                       /* identify traps */
  851.                 flag = yrepcount = 0;
  852.                 cursors();
  853.                 lprc('\n');
  854.                 for (j=playery-1; j<playery+2; j++)
  855.                     {
  856.                     if (j < 0)
  857.                         j=0;
  858.                     if (j >= MAXY)
  859.                         break;
  860.                     for (i=playerx-1; i<playerx+2; i++)
  861.                         {
  862.                         if (i < 0) 
  863.                             i=0;
  864.                         if (i >= MAXX) 
  865.                             break;
  866.                         switch(item[i][j])
  867.                             {
  868.                             case OTRAPDOOR:     case ODARTRAP:
  869.                             case OTRAPARROW:    case OTELEPORTER:
  870.                             case OPIT:
  871.                                 lprcat("\nIts ");
  872.                                 lprcat(objectname[item[i][j]]);
  873.                                 flag++;
  874.                             };
  875.                         }
  876.                     }
  877.                 if (flag==0) 
  878.                     lprcat("\nNo traps are visible");
  879.                 return;
  880.  
  881. #if WIZID
  882.             case '_':   /*  this is the fudge player password for wizard mode*/
  883.                         yrepcount=0;    cursors(); nomove=1;
  884. # ifndef MSDOS
  885.                         if (userid!=wisid)
  886.                             {
  887.                             lprcat("Sorry, you are not empowered to be a wizard.\n");
  888.                             scbr(); /* system("stty -echo cbreak"); */
  889.                             lflush();  return;
  890.                             }
  891. # endif
  892.                         if (getpassword()==0)
  893.                             {
  894.                             scbr(); /* system("stty -echo cbreak"); */ return;
  895.                             }
  896.                         wizard=1;  scbr(); /* system("stty -echo cbreak"); */
  897.                         for (i=0; i<6; i++)  c[i]=70;  iven[0]=iven[1]=0;
  898.                         take(OPROTRING,50);   take(OLANCE,25);  c[WIELD]=1;
  899.                         c[LANCEDEATH]=1;   c[WEAR] = c[SHIELD] = -1;
  900.                         raiseexperience(6000000L);  c[AWARENESS] += 25000;
  901.                         {
  902.                         register int i,j;
  903.                         for (i=0; i<MAXY; i++)
  904.                             for (j=0; j<MAXX; j++)  know[j][i]=KNOWALL;
  905.                         for (i=0; i<SPNUM; i++) spelknow[i]=1;
  906.                         for (i=0; i<MAXSCROLL; i++)  scrollname[i][0]=' ';
  907.                         for (i=0; i<MAXPOTION; i++)  potionname[i][0]=' ';
  908.                         }
  909.                         for (i=0; i<MAXSCROLL; i++)
  910.                           if (strlen(scrollname[i])>2) /* no null items */
  911.                             { item[i][0]=OSCROLL; iarg[i][0]=i; }
  912.                         for (i=MAXX-1; i>MAXX-1-MAXPOTION; i--)
  913.                           if (strlen(potionname[i-MAXX+MAXPOTION])>2) /* no null items */
  914.                             { item[i][0]=OPOTION; iarg[i][0]=i-MAXX+MAXPOTION; }
  915.                         for (i=1; i<MAXY; i++)
  916.                             { item[0][i]=i; iarg[0][i]=0; }
  917.                         for (i=MAXY; i<MAXY+MAXX; i++)
  918.                             { item[i-MAXY][MAXY-1]=i; iarg[i-MAXY][MAXY-1]=0; }
  919.             for (i=MAXX+MAXY; i<MAXOBJECT; i++)
  920.                 {
  921.                 item[MAXX-1][i-MAXX-MAXY]=i;
  922.                 iarg[MAXX-1][i-MAXX-MAXY]=0;
  923.                 }
  924.                         c[GOLD]+=250000;    drawscreen();   return;
  925. #endif
  926.  
  927.             };
  928.         }
  929.     }
  930.  
  931. parse2()
  932.     {
  933.     if (c[HASTEMONST]) movemonst(); movemonst(); /* move the monsters       */
  934.     randmonst();    regen();
  935.     }
  936.  
  937. static run(dir)
  938.     int dir;
  939.     {
  940.     register int i;
  941.     i=1; while (i)
  942.         {
  943.         i=moveplayer(dir);
  944.         if (i>0) {  if (c[HASTEMONST]) movemonst();  movemonst(); randmonst(); regen(); }
  945.         if (hitflag) i=0;
  946.         if (i!=0)  showcell(playerx,playery);
  947.         }
  948.     }
  949.  
  950. /*
  951.     function to wield a weapon
  952.  */
  953. static wield()
  954.     {
  955.     register int i;
  956.     while (1)
  957.         {
  958.         if ((i = whatitem("wield (- for nothing)")) == '\33')
  959.         return;
  960.         if (i != '.')
  961.             {
  962.             if (i=='*')
  963.                 {
  964.                 i = showwield();
  965.                 cursors();
  966.                 }
  967.             if ( i == '-' )
  968.                 {
  969.                 c[WIELD] = -1 ;
  970.                 bottomline();
  971.                 return;
  972.                 }
  973.             if (i && i != '.')
  974.                 if (iven[i-'a']==0)
  975.                     { ydhi(i); return; }
  976.                 else if (iven[i-'a']==OPOTION)
  977.                     { ycwi(i); return; }
  978.             else if (iven[i-'a']==OSCROLL)
  979.                     { ycwi(i); return; }
  980.             else if ((c[SHIELD]!= -1) && (iven[i-'a']==O2SWORD))
  981.                     { lprcat("\nBut one arm is busy with your shield!");
  982.                       return; }
  983.             else
  984.                 {
  985.                 c[WIELD]=i-'a';
  986.                 if (iven[i-'a'] == OLANCE)
  987.                     c[LANCEDEATH]=1;
  988.                 else c[LANCEDEATH]=0;
  989.                 bottomline();
  990.                 return;
  991.                 }
  992.             }
  993.         }
  994.     }
  995.  
  996. /*
  997.     common routine to say you don't have an item
  998.  */
  999. static ydhi(x)
  1000.     int x;
  1001.     { cursors();  lprintf("\nYou don't have item %c!",x); }
  1002. static ycwi(x)
  1003.     int x;
  1004.     { cursors();  lprintf("\nYou can't wield item %c!",x); }
  1005.  
  1006. /*
  1007.     function to wear armor
  1008.  */
  1009. static wear()
  1010.     {
  1011.     register int i;
  1012.     while (1)
  1013.         {
  1014.         if ((i = whatitem("wear"))=='\33')
  1015.             return;
  1016.         if (i != '.' && i != '-')
  1017.             {
  1018.             if (i=='*')
  1019.                 {
  1020.                 i = showwear();
  1021.                 cursors();
  1022.                 }
  1023.             if (i && i != '.')
  1024.                 switch(iven[i-'a'])
  1025.                     {
  1026.                     case 0:
  1027.                         ydhi(i);
  1028.                         return;
  1029.                     case OLEATHER:  case OCHAIN:  case OPLATE:
  1030.                     case ORING:     case OSPLINT: case OPLATEARMOR:
  1031.                     case OSTUDLEATHER:            case OSSPLATE:
  1032.                         if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; }
  1033.                             c[WEAR]=i-'a';  bottomline(); return;
  1034.                     case OSHIELD:   if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; }
  1035.                                 if (iven[c[WIELD]]==O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; }
  1036.                                 c[SHIELD] = i-'a';  bottomline(); return;
  1037.                     default:    lprcat("\nYou can't wear that!");
  1038.                     };
  1039.             }
  1040.         }
  1041.     }
  1042.  
  1043. /*
  1044.     function to drop an object
  1045.  */
  1046. static dropobj()
  1047.     {
  1048.     register int i;
  1049.     register char *p;
  1050.     long amt;
  1051.  
  1052.     p = &item[playerx][playery];
  1053.     while (1)
  1054.         {
  1055.         if ((i = whatitem("drop"))=='\33')  
  1056.         return;
  1057.     if (i=='*') 
  1058.         {
  1059.         i = showstr(TRUE);
  1060.         cursors();
  1061.         }
  1062.     if ( i != '-' )
  1063.             {
  1064.             if (i=='.') /* drop some gold */
  1065.                 {
  1066.                 if (*p) { lprcat("\nThere's something here already!"); return; }
  1067.                 lprcat("\n\n");
  1068.                 cl_dn(1,23);
  1069.                 lprcat("How much gold do you drop? ");
  1070.                 if ((amt=readnum((long)c[GOLD])) == 0) return;
  1071.                 if (amt>c[GOLD])
  1072.                     {
  1073. #ifndef MSDOS
  1074.             lprcat("\n");
  1075. #endif MSDOS
  1076.             lprcat("You don't have that much!");
  1077.             return; }
  1078.                 if (amt<=32767)
  1079.                     { *p=OGOLDPILE; i=amt; }
  1080.                 else if (amt<=327670L)
  1081.                     { *p=ODGOLD; i=amt/10; amt = 10L*i; }
  1082.                 else if (amt<=3276700L)
  1083.                     { *p=OMAXGOLD; i=amt/100; amt = 100L*i; }
  1084.                 else if (amt<=32767000L)
  1085.                     { *p=OKGOLD; i=amt/1000; amt = 1000L*i; }
  1086.                 else
  1087.                     { *p=OKGOLD; i=32767; amt = 32767000L; }
  1088.                 c[GOLD] -= amt;
  1089. #ifndef MSDOS
  1090.                 lprintf("You drop %d gold pieces",(long)amt);
  1091. #else
  1092.                 lprintf("\nYou drop %d gold pieces",(long)amt);
  1093. #endif MSDOS
  1094.                 iarg[playerx][playery]=i; bottomgold();
  1095.                 know[playerx][playery]=0; dropflag=1;  return;
  1096.                 }
  1097.         if (i)
  1098.         {
  1099.         drop_object(i-'a');
  1100.         return;
  1101.         }
  1102.             }
  1103.         }
  1104.     }
  1105.  
  1106. static int floor_consume( search_item, cons_verb )
  1107. int search_item;
  1108. char *cons_verb;
  1109.     {
  1110.     register int i;
  1111.     char tempc;
  1112.  
  1113.     cursors();
  1114.     i = item[playerx][playery];
  1115.  
  1116.     /* item not there, quit
  1117.     */
  1118.     if (i != search_item)
  1119.         return( 0 );
  1120.  
  1121.     /* item there.  does the player want to consume it?
  1122.     */
  1123.     lprintf("\nThere is %s", objectname[i] );
  1124.     if (i==OSCROLL)
  1125.         if (scrollname[iarg[playerx][playery]][0])
  1126.             lprintf(" of%s", scrollname[iarg[playerx][playery]]);
  1127.     if (i==OPOTION)
  1128.         if (potionname[iarg[playerx][playery]][0])
  1129.             lprintf(" of%s", potionname[iarg[playerx][playery]]);
  1130.     lprintf(" here.  Do you want to %s it?", cons_verb );
  1131.  
  1132.     if ((tempc = getyn()) == 'n' )
  1133.         return( 0 );                /* item there, not consumed */
  1134.     else if (tempc != 'y')
  1135.         {
  1136.         lprcat(" aborted");
  1137.         return( -1 );               /* abort */
  1138.         }
  1139.  
  1140.     /* consume the item.
  1141.     */
  1142.     switch( i )
  1143.         {
  1144.         case OCOOKIE:
  1145.             outfortune();
  1146.             forget();
  1147.             break;
  1148.         case OBOOK:
  1149.             readbook( iarg[playerx][playery] );
  1150.             forget();
  1151.             break;
  1152.         case OPOTION:
  1153.             quaffpotion( iarg[playerx][playery] );
  1154.             forget();
  1155.             break;
  1156.         case OSCROLL:
  1157.             /* scrolls are tricky because of teleport.
  1158.             */
  1159.             i = iarg[playerx][playery];
  1160.             know[playerx][playery] = 0;
  1161.             item[playerx][playery] = iarg[playerx][playery] = 0 ;
  1162.             read_scroll( i );
  1163.             break;
  1164.         }
  1165.     return( 1 );
  1166.     }
  1167.  
  1168. static int consume( search_item, prompt, showfunc )
  1169. int search_item ;
  1170. char *prompt;
  1171. int (*showfunc)();
  1172.     {
  1173.     register int i;
  1174.  
  1175.     while (1)
  1176.         {
  1177.         if ((i = whatitem( prompt )) == '\33')
  1178.             return;
  1179.         if (i != '.' && i != '-')
  1180.             {
  1181.             if (i == '*')
  1182.                 {
  1183.                 i = showfunc();
  1184.                 cursors();
  1185.                 }
  1186.             if (i && i != '.')
  1187.                 {
  1188.                 switch (iven[i-'a'])
  1189.                     {
  1190.                     case OSCROLL:
  1191.                         if ( search_item != OSCROLL )
  1192.                             {
  1193.                             lprintf("\nYou can't %s that.", prompt );
  1194.                             return;
  1195.                             }
  1196.                         read_scroll( ivenarg[i-'a'] );
  1197.                         break;
  1198.                     case OBOOK:
  1199.                         if ( search_item != OSCROLL )
  1200.                             {
  1201.                             lprintf("\nYou can't %s that.", prompt );
  1202.                             return;
  1203.                             }
  1204.                         readbook( ivenarg[i-'a'] );
  1205.                         break;
  1206.                     case OCOOKIE:
  1207.                         if ( search_item != OCOOKIE )
  1208.                             {
  1209.                             lprintf("\nYou can't %s that.", prompt );
  1210.                             return;
  1211.                             }
  1212.                         outfortune();
  1213.                         break;
  1214.                     case OPOTION:
  1215.                         if ( search_item != OPOTION )
  1216.                             {
  1217.                             lprintf("\nYou can't %s that.", prompt );
  1218.                             return;
  1219.                             }
  1220.                         quaffpotion( ivenarg[i-'a'], TRUE );
  1221.                         break;
  1222.                     case 0:
  1223.                         ydhi(i);
  1224.                         return;
  1225.                     default:
  1226.                         lprintf("\nYou can't %s that.", prompt );
  1227.                         return;
  1228.                     }
  1229.                 iven[i-'a'] = 0;
  1230.                 return;
  1231.                 }
  1232.             }
  1233.         }
  1234.     }
  1235.  
  1236. /*
  1237.     function to ask what player wants to do
  1238.  */
  1239. static whatitem(str)
  1240.     char *str;
  1241.     {
  1242.     int i=0;
  1243.     cursors();  lprintf("\nWhat do you want to %s [* for all] ? ",str);
  1244.     while (i>'z' || (i<'a' && i!='-' && i!='*' && i!='\33' && i!='.'))
  1245.         i=ttgetch();
  1246.     if (i=='\33')
  1247.         lprcat(" aborted");
  1248.     return(i);
  1249.     }
  1250.  
  1251. /*
  1252.     subroutine to get a number from the player
  1253.     and allow * to mean return amt, else return the number entered
  1254.  */
  1255. unsigned long readnum(mx)
  1256.     long mx;
  1257.     {
  1258.     register int i;
  1259.     register unsigned long amt=0;
  1260.  
  1261.     sncbr();
  1262.     /* allow him to say * for all gold 
  1263.     */
  1264.     if ((i=ttgetch()) == '*')
  1265.         amt = mx;
  1266.     else
  1267.         /* read chars into buffer, deleting when requested */
  1268.     while (i != '\n')
  1269.         {
  1270.         if (i=='\033') { scbr(); lprcat(" aborted"); return(0); }
  1271.         if ((i <= '9') && (i >= '0') && (amt<999999999))
  1272.             amt = amt*10+i-'0';
  1273.         if ((i=='\010') || (i=='\177'))
  1274.             amt = (long)(amt / 10) ;
  1275.         i = ttgetch();
  1276.         }
  1277.     scbr();
  1278.     return(amt);
  1279.     }
  1280.  
  1281. #ifdef HIDEBYLINK
  1282. /*
  1283.  *  routine to zero every byte in a string
  1284.  */
  1285. szero(str)
  1286.     register char *str;
  1287.     {
  1288.     while (*str)
  1289.         *str++ = 0;
  1290.     }
  1291. #endif HIDEBYLINK
  1292.  
  1293. #ifdef TIMECHECK
  1294. /*
  1295.  *  routine to check the time of day and return 1 if its during work hours
  1296.  *  checks the file ".holidays" for forms like "mmm dd comment..."
  1297.  */
  1298. int playable()
  1299.     {
  1300.     long g_time,time();
  1301.     int hour,day,year;
  1302.     char *date,*month,*p;
  1303.  
  1304.     time(&g_time);  /* get the time and date */
  1305.     date = ctime(&g_time); /* format: Fri Jul  4 00:27:56 EDT 1986 */
  1306.     year = atoi(date+20);
  1307.     hour = (date[11]-'0')*10 + date[12]-'0';
  1308.     day  = (date[8]!=' ') ? ((date[8]-'0')*10 + date[9]-'0') : (date[9]-'0');
  1309.     month = date+4;  date[7]=0; /* point to and NULL terminate month */
  1310.  
  1311.     if (((hour>=8 && hour<17)) /* 8AM - 5PM */
  1312.         && strncmp("Sat",date,3)!=0     /* not a Saturday */
  1313.         && strncmp("Sun",date,3)!=0)    /* not a Sunday */
  1314.             {
  1315.         /* now check for a .holidays datafile */
  1316.             lflush();
  1317.             if (lopen(holifile) >= 0)
  1318.                 for ( ; ; )
  1319.                     {
  1320.                     if ((p=lgetw())==0) break;
  1321.                     if (strlen(p)<6) continue;
  1322.                     if ((strncmp(p,month,3)==0) && (day==atoi(p+4)) && (year==atoi(p+7)))
  1323.                         return(0); /* a holiday */
  1324.                     }
  1325.             lrclose();  lcreat((char*)0);
  1326.             return(1);
  1327.             }
  1328.     return(0);
  1329.     }
  1330. #endif TIMECHECK
  1331.